package com.syh.core.ddd.event;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.SessionHolder;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionSynchronizationManager;


/**
 *  事件消费AOP,用于拦截异步消费方法,方法创建事务,但配置了声明式事务后则废除
 *0
 */
//@Component
//@Aspect
public class EventTransactionAspect {

	private Logger logger=LoggerFactory.getLogger(EventTransactionAspect.class);

	@Autowired
	private HibernateTransactionManager hibernateTransactionManager;

	private Session session;
	private Transaction transaction;

	@Pointcut("@annotation(com.syh.core.ddd.event.annotation.DomainEventHandle)")
    public void pointCut(){
		}


	@Before("pointCut()")
	public void before(JoinPoint joinPoint) {
    //进入方法判断当前线程是否是事务,没有则开启事务处理,不经过service的话是没有事务处理的
		//声明式事务管理可以避免这个问题,而注解式事务不行
		try{
			hibernateTransactionManager.getSessionFactory().getCurrentSession();
		}catch (Exception e){
			session = hibernateTransactionManager.getSessionFactory().openSession();
			session.setFlushMode(FlushMode.AUTO);
			SessionHolder sessionHolder = new SessionHolder(session);
			TransactionSynchronizationManager.bindResource(hibernateTransactionManager.getSessionFactory(), sessionHolder);
			transaction=session.beginTransaction();
		}
	}

	@After("pointCut()")
	public void after(JoinPoint joinPoint){
		if(transaction !=null){
			transaction.commit();
		}
	}
	@AfterThrowing("pointCut()")
	public void afterThrowing(){
		//抛出异常回滚事务
		if(transaction !=null){
			transaction.rollback();
		}
	}
	@AfterReturning("pointCut()")
	public void afterReturn(JoinPoint joinPoint){
		if(session !=null){
			session.close();
		}

	}

}
